#!/usr/bin/env python
# coding=utf-8


import os
import re
import time
from deploy_sshops import SSHConnection
from deploy_package import PackageApp
from deploy_log import log_start
logger = log_start('publish')


class PublishApp(object):
    
    def __init__(self,params,hostInfo):

        self.params = params
        self.hostInfo = hostInfo

        # self.packname = self.params['packname']
        # self.systemUser=self.hostInfo['sshuser']
        # self.app_type =self.params['app_type'] 
        # self.upload_path = self.params['upload_path']
        # self.backup_path = self.params['backup_path']
        # self.app_build_cmd = self.params['app_build_cmd']
        # self.app_deploy_path =  self.params['app_deploy_path']
        # self.workspace = self.params['workspace']
        # self.tarnodepath = os.path.join(self.workspace,'dist')
        # self.envname = self.params['app_env']
        
        # jenkins 
        self.packname = self.params.jobname
        self.systemUser=self.hostInfo['sshuser']
        self.app_type =self.params.app_type
        self.app_deploy_path = self.params.app_deploy_path
        self.upload_path = "{}_upload".format(self.params.app_deploy_path)  
        self.app_deploy_path =  self.params.app_deploy_path
        self.workspace = self.params.workspace
        self.tarnodepath = os.path.join(self.workspace,'dist')
        self.do_what =  self.params.do_what
        #self.backup_path = self.params.backup_path

        self.app_build_cmd = self.params.app_build_cmd
        self.app_stop_cmd = self.params.app_stop_cmd
        self.app_start_cmd =  self.params.app_start_cmd

        self.options = {
            "jar": "java",
            "jar-lib":"java",
            "war": "java",
            "vue":"node",
            "node":"node"
         
        }


    def print(self):
        print("字典:\n\n",self.hostInfo['sshuser'])

    def find_file(self,path,filename):
        result = []
        for root, lists, files in os.walk(path):
            for file in files:
                regex = re.compile(r'%s' % filename)
                matchObj = regex.match(file)
                if matchObj:
                # if filename in file:
                    f = os.path.join(root, file)
                    result.append(f)
                    logger.info('匹配文件:{}'.format(f))
        if len(result)>0:
            return result[0]
        else:
            logger.error("没有匹配到文件")
            return False

    def run(self):
        if  self.do_what == "publish":
            Package = PackageApp(self.params)
            Package.run()
            # 默认发布需要编译打包 
        elif self.do_what == "pre-publish":
            self.workspace = self.workspace.replace('pro','pre')  
            # 不打包,使用pre预发包


        self.sftp_remote_transfer()

        if  self.app_type == 'game_node':
            self.app_build() # 远程构建
        else:
            self.restart_services() 

    
    def app_build(self):
        """ build """
        with SSHConnection(self.hostInfo) as ssh:
            cmd  = "cd {0}/;{1} ".format(self.app_deploy_path,self.app_build_cmd)
            ssh.exec_cmd(cmd)

    def stop_services(self):
        """ stop """
        with SSHConnection(self.hostInfo) as ssh:
            cmd  = "cd {0}; {1} >/dev/null 2>&1 &".format(self.app_deploy_path,self.app_stop_cmd)
            logger.info("停止服务: {0}".format(cmd))
            ssh.exec_cmd(cmd,show=False)
 
    def restart_services(self):
        """
        resatrt
        """
        type_name = self.options[self.app_type.lower()]
        if self.app_start_cmd:
            with SSHConnection(self.hostInfo) as ssh:
                cmd  = "cd {0}; {1} >/dev/null 2>&1 &".format(self.app_deploy_path,self.app_stop_cmd)
                logger.info("停止服务: {0}".format(cmd))
                ssh.exec_cmd(cmd,show=False)
                time.sleep(3) #  等待服务停止
                cmd  = "source /etc/profile; cd {0};{1} >/dev/null 2>&1;sleep 10;netstat -pntl |grep {2}|grep -v grep".format(self.app_deploy_path,self.app_start_cmd,type_name)
                v = ssh.exec_cmd(cmd,show=True)
                logger.info("启动服务: {0} \n{1}".format(self.app_start_cmd,v))
            
    

    def sftp_remote_transfer(self):
        with SSHConnection(self.hostInfo) as ssh:
            #mv_cmd = "rm -rf  {0}_bak ; mv  {0} {0}_bak >/dev/null 2>&1 &".format(self.app_deploy_path)
            #logger.info("++++重命名deploy目录........")
            #ssh.exec_cmd(mv_cmd)
            if self.app_type == "jar-lib":
                filename = '{}.*.tar.gz'.format(self.packname)
                pkg = self.find_file(self.workspace,filename)
                self.workspace,self.packname = os.path.split(pkg) # jar lib已有tar包地址拼接
            else:
                self.packname = '{}.tar.gz'.format(self.packname)
            
            logger.info("{0} - {1}".format(self.workspace,self.packname))


            
            logger.info("++++目录检查........")
            ssh.exec_cmd("mkdir -p -m755 {0} {1}  >/dev/null 2>&1 &".format(self.upload_path,self.app_deploy_path)) 
            chown_cmd = "chown -R {0}.{0} {1} {2} >/dev/null 2>&1 & ".format( self.systemUser,self.upload_path,self.app_deploy_path)
            ssh.exec_cmd(chown_cmd)  
            
            
            backup_cmd = "cd {0}/;cp {1} {1}.bak  >/dev/null 2>&1 &".format(self.upload_path,self.packname)
            logger.info("++++正在备份文件........")
            ssh.exec_cmd(backup_cmd)
            
            local_file = os.path.join(self.workspace,self.packname)
            logger.info("++++正在推送文件[{}]........".format(self.packname))
            ssh.sftp_put_file(local_file,self.upload_path)


            if  self.app_type == "jar-lib":
                cmd = "cd {0}/;tar zxf {1} -C  {2} --strip-components 1".format(self.upload_path,self.packname,self.app_deploy_path) # --strip-components 1 跳过一层解压目录
            else:
                cmd = "cd {0}/;tar zxf {1} -C  {2}".format(self.upload_path,self.packname,self.app_deploy_path)    

            logger.info("++++执行文件解压........")
            v = ssh.exec_cmd(cmd)
            logger.info(v)



    def Custom_game_node(self):
        # 不管是否已经部署过，都创建目录，并赋权，省了处理逻辑
        mkdirdmd = "mkdir -p -m777 %s %s %s" % (
            self.app_deploy_path, self.backup_path, self.upload_path)
        self.sops.sshtool.exec_shell(mkdirdmd)


        logger.info("++++执行文件检查命令：%s " % check_deploy_cmd)
        cresult = self.sops.sshtool.exec_shell(check_deploy_cmd)
        if int(cresult) == 1:
            logger.info("++++对现有程序进行备份,请等待")
            backcmd = '''cd %s;rm -rf %s zjs-old;\mv %s/%s %s/''' \
                      % (self.back_path, self.tar_appname, self.upload_path, self.tar_appname, self.back_path,)
            self.sops.sshtool.exec_shell(backcmd)

        else:
            logger.info("文件不存在或初次安装")



        if self.envname.upper() == 'PN1':
            remote_v_md5_cmd = "md5sum %s	|awk '{print $1}'" % os.path.join(self.upload_path,
                                                                            'build_result/version.manifest')
            r_v_md5 = self.sops.sshtool.exec_shell(remote_v_md5_cmd)
            l_v_md5, time = self.check_md5(os.path.join(
                self.packpath, 'build_result/version.manifest'))
        else:
            remote_v_md5_cmd = "md5sum %s	|awk '{print $1}'" % os.path.join(
                self.upload_path, 'zsj/build_result/version.manifest')
            r_v_md5 = self.sops.sshtool.exec_shell(remote_v_md5_cmd)
            l_v_md5, time = self.check_md5(os.path.join(
                self.packpath, 'zsj/build_result/version.manifest'))

        if r_v_md5 == l_v_md5:
            logger.info("js文件上传成功，等待更新")
        else:
            logger.error("js文件上传失败，检查")

    def update_app(self):
        try:

            if self.envname.upper() == 'PN1':

                mv_up_rename_cmd = 'cd %s; mkdir -p zsj-up;mv build_result zsj-up/; mv zsj-up %s' % (
                    self.upload_path, self.deploy_path)
                self.sops.sshtool.exec_shell(mv_up_rename_cmd)
                mv_old_rename_cmd = 'cd %s;mv zsj zsj-old;mv zsj-up zsj;chmod 777 -R zsj' % self.deploy_path
                self.sops.sshtool.exec_shell(mv_old_rename_cmd)
                old_del_cmd = 'cd %s;rm -rf zsj-old ' % (self.deploy_path)
                self.sops.sshtool.exec_shell(old_del_cmd)
                up_oss_cmd = 'cd %s/zsj/;\cp -R build_result /hotupdate/zsj/;' % (
                    self.deploy_path)
                self.sops.sshtool.exec_shell(up_oss_cmd)
            else:
                mv_up_rename_cmd = 'cd %s;mv zsj ../zsj-up;' % self.upload_path
                self.sops.sshtool.exec_shell(mv_up_rename_cmd)
                mv_old_rename_cmd = 'cd %s;mv zsj zsj-old; ' % self.deploy_path
                self.sops.sshtool.exec_shell(mv_old_rename_cmd)
                up_cmd = 'cd %s;mv zsj-up zsj; rm -rf zsj-old' % (
                    self.deploy_path)
                self.sops.sshtool.exec_shell(up_cmd)

            # del_cmd = 'cd %s;rm -rf upload/' % (self.deploy_path)
            # self.sops.sshtool.exec_shell(del_cmd)

        except BaseException as e:
            self.utils.app_dict["status"] = 500
            self.utils.app_dict["exceptinfo"] = str(e)
            logger.error("更新失败，请检查 %s " % str(e))
        finally:
            self.sops.sshtool.close_ssh()
            value = self.utils.cmdb.create_publish_by_params(
                self.utils.app_dict)
            logger.info(value)

    def main_start(self):
        try:
            if self.tar_appname:
                self.utils.app_dict['filemd5'] = self.tarfilemd5
                md5_check_cmd = "md5sum %s|awk '{print $1}'" % os.path.join(
                    self.upload_path, self.tar_appname)
                remote_md5 = self.sops.sshtool.exec_shell(
                    md5_check_cmd, error_info=False)
                logger.info("Remote_md5:%s" % remote_md5)
                logger.info("Local_md5:%s" % self.tarfilemd5)
                params = {
                    'appname': self.appname,
                    'commitid': self.git_commitid,
                    'status': '0'
                }
                gitresu = self.utils.cmdb.get_publish_by_params(params)
                if self.tarfilemd5 == remote_md5 and gitresu:
                    logger.info("发布文件MD5一致,git commit ID 与上次一样，不需要处理，仅作重启！")
                    self.sops.main_start('restart')
                else:
                    self.pack.main_start()
                    if self.packtype == 'js':
                        self.game_app()
            else:
                self.pack.main_start()
                if self.packtype == 'js':
                    self.game_app()

        except BaseException as e:
            self.utils.app_dict["status"] = 500
            self.utils.app_dict["exceptinfo"] = str(e)
            logger.error("发布失败，请检查 %s " % str(e))
        finally:
            self.sops.sshtool.close()
            value = self.utils.cmdb.create_publish_by_params(
                self.utils.app_dict)
            logger.info(value)
